package com.brillilab.service.core.kit.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.entity.PageVo;
import com.brillilab.dao.mapper.global.GlobalKitMapper;
import com.brillilab.dao.mapper.kit.KitMapper;
import com.brillilab.dao.mapper.kit.KitSpecMapper;
import com.brillilab.dao.mapper.kit.ReagentMapper;
import com.brillilab.dao.mapper.kit.ReagentTypeMapper;
import com.brillilab.dao.mapper.system.IdUtilMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.kit.KitEnum.Classify;
import com.brillilab.domain.enums.system.IdUtilTypeEnum;
import com.brillilab.domain.pa.kit.ReagentSearchPa;
import com.brillilab.domain.pa.kit.SampleSearchPa;
import com.brillilab.domain.po.elsearch.EsReagent;
import com.brillilab.domain.po.elsearch.EsSample;
import com.brillilab.domain.po.global.GlobalKit;
import com.brillilab.domain.po.kit.*;
import com.brillilab.domain.po.system.FileManage;
import com.brillilab.domain.po.system.IdUtil;
import com.brillilab.domain.po.topics.TopicExperiment;
import com.brillilab.domain.po.topics.TopicTarget;
import com.brillilab.domain.vo.kit.*;
import com.brillilab.service.core.elsearch.IEsReagentService;
import com.brillilab.service.core.elsearch.IEsSampleService;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.global.IGlobalKitService;
import com.brillilab.service.core.kit.IKitService;
import com.brillilab.service.core.kit.IReagentTypeHideService;
import com.brillilab.service.core.kit.IReagentTypeService;
import com.brillilab.service.core.method.IMethodTypeService;
import com.brillilab.service.core.system.IDictService;
import com.brillilab.service.core.system.IFileManageService;
import com.brillilab.service.core.topics.ITopicExperimentService;
import com.brillilab.service.core.topics.ITopicTargetService;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class KitServiceImpl implements IKitService {
	@Resource
	private KitMapper kitMapper;
	@Resource
	private IdUtilMapper idUtilMapper;
	@Resource
	private ReagentTypeMapper reagentTypeMapper;
	@Resource
	private IDictService dictService;
	@Resource
	private KitSpecMapper kitSpecMapper;
	@Resource
	private ReagentMapper reagentMapper;
	@Resource
	private GlobalKitMapper globalKitMapper;

	@Resource
	private IFileManageService fileManageService;
	@Resource
	private IEsReagentService esReagentService;
	@Resource
	private IEsSampleService esSampleService;
	@Resource
	private IReagentTypeHideService reagentTypeHideService;
	@Resource
	private IReagentTypeService reagentTypeService;
	@Resource
	private ITopicTargetService topicTargetService;
	@Resource
	private ITopicExperimentService topicExperimentService;
	@Resource
	private IMethodTypeService methodTypeService;

	@Override
	public void assertIsLabKit(Long labId, Long kitId) {
		Kit kit = kitMapper.selectById(kitId);
		Assert.isTrue(kit != null && kit.getLabId().equals(labId), "您没有操作权限");
	}

	@Override
	public Long getKitGroup() {
		IdUtil idUtil = new IdUtil();
		idUtil.setName(IdUtilTypeEnum.KIT_GROUP.getType());
		int insert = idUtilMapper.insert(idUtil);
		Assert.isTrue(insert == 1, "添加失败");
		return idUtil.getId();
	}

	@Override
	public Kit insert(Kit entity) {
		Assert.isTrue(StringUtils.isNotBlank(entity.getName()) && entity.getUnit() != null && entity.getZone() != null
				&& entity.getReagentTypeId() != null, "试剂信息不全");
		if (entity.getKitGroup() == null) {
			entity.setKitGroup(this.getKitGroup());
		}
		Integer insert = kitMapper.insert(entity);
		Assert.isTrue(insert == 1, "添加失败");
		return entity;
	}

	@Override
	public boolean deleteById(Long id) {
		Assert.notNull(id, "删除ID不能为空");
		Kit kit = new Kit();
		kit.setId(id);
		kit.setIsDelete(IsDeleteEnum.YES.getValue());
		return this.updateById(kit);
	}

	@Override
	public boolean updateById(Kit entity) {
		entity.setUpdateTime(new Date());
		Integer i = kitMapper.updateById(entity);
		return i == 1;
	}

	@Override
	public Kit selectById(Long id) {
		return kitMapper.selectById(id);
	}

	@Override
	public PageVo<KitInfoListVo> reagentList(ReagentSearchPa pa,Long labId,Long labMemberId) {
		int totalRow = 0;
		Map<Integer, String> unitMap = dictService.getUnitMap();
		Map<Long, String> reagentTypeMap = dictService.getReagentTypeMap(pa.getLabId());
		List<KitInfoListVo> kitInfoList = new ArrayList<>();
		List<Long> reagentTypeIds = null;
		if (pa.getReagentTypeId() != null) {// 查询是否有二级分类
			reagentTypeIds = new ArrayList<Long>();
			reagentTypeIds.add(pa.getReagentTypeId());
			List<ReagentTypeVo> list = reagentTypeMapper.selectReagentType(pa.getReagentTypeId(), pa.getLabId(), null);
			if (list != null && list.size() > 0) {
				List<Long> ids = list.stream().map(ReagentTypeVo::getReagentTypeId).collect(Collectors.toList());
				reagentTypeIds.addAll(ids);
			}
		}

		if (isSenior(pa)) {// 启用高级搜索
			pa.setReagentTypeIds(reagentTypeIds);
			Page<EsReagent> esPage = esReagentService.queryList(pa);
			totalRow = (int) esPage.getTotalElements();
			List<EsReagent> kitList = esPage.getContent();
			if (kitList != null && kitList.size() > 0) {
				List<Long> kitIds = kitList.stream().map(EsReagent::getKitId).collect(Collectors.toList());
				Map<Long, List<FileManage>> fileMap = fileManageService.selectList(OssFileEnum.KitInstructionFile, kitIds).stream().collect(Collectors.groupingBy(FileManage::getReferDataId));
				kitList.forEach(kit -> {
					KitInfoListVo vo = new KitInfoListVo();
					vo.setKitId(kit.getKitId());
					vo.setKitName(kit.getKitName());
					vo.setReagentTypeId(kit.getReagentTypeId());
					vo.setReagentTypeName(reagentTypeMap.get(kit.getReagentTypeId()));
					vo.setUnit(kit.getUnit());
					vo.setUnitName(unitMap.get(kit.getUnit()));
					vo.setKitType(kit.getKitType());
					vo.setInstructionFileList(fileMap.get(kit.getKitId()));
					kitInfoList.add(vo);
				});
			}

		} else {// 试剂列表查询
			PageHelper.startPage(pa.getPageNum(), pa.getPageSize());
			List<Kit> kitList = kitMapper.selectReagentList(pa.getLabId(), reagentTypeIds, pa.getSort());
			if (kitList != null && kitList.size() > 0) {
				PageVo<Kit> pageVo = new PageVo<Kit>(kitList);
				totalRow = pageVo.getTotalRow();
				List<Long> kitIds = kitList.stream().map(Kit::getId).collect(Collectors.toList());
				Map<Long, List<FileManage>> fileMap = fileManageService.selectList(OssFileEnum.KitInstructionFile, kitIds).stream().collect(Collectors.groupingBy(FileManage::getReferDataId));
				kitList.forEach(kit -> {
					KitInfoListVo vo = new KitInfoListVo();
					vo.setKitId(kit.getId());
					vo.setKitName(kit.getName());
					vo.setReagentTypeId(kit.getReagentTypeId());
					vo.setReagentTypeName(reagentTypeMap.get(kit.getReagentTypeId()));
					vo.setUnit(kit.getUnit());
					vo.setUnitName(unitMap.get(kit.getUnit()));
					vo.setKitType(kit.getKitType());
					vo.setInstructionFileList(fileMap.get(kit.getId()));
					kitInfoList.add(vo);
				});
			}
		}
		return new PageVo<KitInfoListVo>(pa.getPageNum(), pa.getPageSize(), totalRow, kitInfoList);
	}

	// 判断是否有搜索条件，有就启动高级搜索
	private boolean isSenior(ReagentSearchPa pa) {
		if (StringUtils.isNotBlank(pa.getSearchName()))
			return true;
		if (pa.getZone() != null)
			return true;
		if (StringUtils.isNotBlank(pa.getCompany()))
			return true;
		if (!CollectionUtils.isEmpty(pa.getSearchFieldList()))
			return true;
		return false;
	}

	@Override
	public PageVo<SampleListVo> sampleList(SampleSearchPa pa,Long labId,Long labMemberId) {
		int totalRow = 0;
		Map<Integer, String> unitMap = dictService.getUnitMap();
		Map<Long, String> reagentTypeMap = dictService.getReagentTypeMap(pa.getLabId());
		List<SampleListVo> sampleList = new ArrayList<>();

		List<Long> reagentTypeIds = null;
		if(pa.getReagentTypeId() == null) {
			//TODO 类型隐藏的处理
			List<ReagentType> myTypes = reagentTypeService.selectList(labId,labMemberId);
			List<ReagentTypeHide> hides=reagentTypeHideService.selectList(labId,labMemberId,BoolEnum.TRUE.getValue());
			List<Long> hideTypeIds=hides.stream().map(ReagentTypeHide::getReagentTypeId).distinct().collect(Collectors.toList());
			reagentTypeIds = myTypes.stream().filter(e -> !hideTypeIds.contains(e.getId())).map(ReagentType::getId).distinct().collect(Collectors.toList());
			pa.setReagentTypeIds(reagentTypeIds);
		}

		if (StringUtils.isNotBlank(pa.getSearchName()) || pa.getZone() != null
				|| !CollectionUtils.isEmpty(pa.getSampleAttr())) {// 启用高级搜索
			Page<EsSample> esPage = esSampleService.queryList(pa);
			totalRow = (int) esPage.getTotalElements();
			List<EsSample> kitList = esPage.getContent();
			if (kitList != null && kitList.size() > 0) {
				kitList.forEach(kit -> {
					SampleListVo vo = new SampleListVo();
					vo.setKitId(kit.getKitId());
					vo.setSampleName(kit.getKitName());
					vo.setReagentTypeId(kit.getReagentTypeId());
					vo.setReagentTypeName(reagentTypeMap.get(kit.getReagentTypeId()));
					vo.setUnit(kit.getUnit());
					vo.setUnitName(unitMap.get(kit.getUnit()));
					vo.setKitGroup(kit.getKitGroup());
					sampleList.add(vo);
				});
			}
		} else {
			PageHelper.startPage(pa.getPageNum(), pa.getPageSize());
			List<Kit> kitList = kitMapper.selectSampleList(pa.getLabId(), pa.getReagentTypeId() , pa.getReagentTypeIds(), pa.getSort());
			PageVo<Kit> pageVo = new PageVo<Kit>(kitList);
			totalRow = pageVo.getTotalRow();
			if (kitList != null && kitList.size() > 0) {
				kitList.forEach(kit -> {
					SampleListVo vo = new SampleListVo();
					vo.setKitId(kit.getId());
					vo.setSampleName(kit.getName());
					vo.setReagentTypeId(kit.getReagentTypeId());
					vo.setReagentTypeName(reagentTypeMap.get(kit.getReagentTypeId()));
					vo.setUnit(kit.getUnit());
					vo.setUnitName(unitMap.get(kit.getUnit()));
					vo.setKitGroup(kit.getKitGroup());
					sampleList.add(vo);
				});
			}
		}
		return new PageVo<SampleListVo>(pa.getPageNum(), pa.getPageSize(), totalRow, sampleList);
	}

	@Override
	public List<Kit> selectListByFromId(Long labId, Long fromId) {
		LambdaQueryWrapper<Kit> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Kit::getLabId, labId);
		wrapper.eq(Kit::getFromId, fromId);
		wrapper.eq(Kit::getIsDelete, IsDeleteEnum.NO.getValue());
		return kitMapper.selectList(wrapper);
	}

	@Override
	public List<RecycleKitVo> selectByIsDelete(Long kitId, Integer isDelete) {
		return kitMapper.selectByIsDelete(kitId, isDelete);
	}

	@Override
	public List<Kit> selectListByReagentType(Long labId, Long reagentTypeId) {
		LambdaQueryWrapper<Kit> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Kit::getLabId, labId);
		wrapper.eq(Kit::getReagentTypeId, reagentTypeId);
		wrapper.eq(Kit::getIsDelete, IsDeleteEnum.NO.getValue());
		return kitMapper.selectList(wrapper);
	}

	@Override
	public List<SampleVo> sampleByKitGroup(Long kitGroup) {
		List<SampleVo> voList = new ArrayList<>();
		LambdaQueryWrapper<Kit> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Kit::getKitGroup, kitGroup);
		wrapper.eq(Kit::getIsDelete, IsDeleteEnum.NO.getValue());
		List<Kit> kitList = kitMapper.selectList(wrapper);
		if (kitList != null && kitList.size() > 0) {
			kitList.forEach(kit -> {
				SampleVo vo = new SampleVo();
				vo.setKit(kit);
				LambdaQueryWrapper<KitSpec> spWrapper = new LambdaQueryWrapper<>();
				spWrapper.eq(KitSpec::getKitId, kit.getId());
				spWrapper.eq(KitSpec::getIsDelete, IsDeleteEnum.NO.getValue());
				KitSpec kitSpec = kitSpecMapper.selectOne(spWrapper);
				vo.setKitSpec(kitSpec);
				LambdaQueryWrapper<Reagent> reWrapper = new LambdaQueryWrapper<>();
				reWrapper.eq(Reagent::getKitId, kit.getId());
				reWrapper.eq(Reagent::getIsDelete, IsDeleteEnum.NO.getValue());
				Reagent reagent = reagentMapper.selectOne(reWrapper);
				vo.setReagent(reagent);
				voList.add(vo);
			});
		}
		return voList;
	}

	@Override
	public int selectKitCount(Long labId) {
		LambdaQueryWrapper<Kit> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Kit::getLabId, labId);
		wrapper.eq(Kit::getIsDelete, IsDeleteEnum.NO.getValue());
		return kitMapper.selectCount(wrapper);
	}

	@Override
	public Map<Long, Long> groupByReagentType(Long labId, Integer classify) {
		Map<Long, Long> groupMap = new HashMap<>();
		List<Map<String, Object>> list = kitMapper.groupByReagentType(labId, classify);
		if (list != null) {
			list.forEach(map -> {
				groupMap.put(Long.valueOf(map.get("reagentTypeId").toString()),
						Long.valueOf(map.get("num").toString()));
			});
		}
		return groupMap;
	}

	@Override
	public boolean updateWarnamount(Long kitId, BigDecimal warnamount) {
		Kit kit = new Kit();
		kit.setId(kitId);
		kit.setWarnamount(warnamount);
		return this.updateById(kit);
	}

	@Override
	public List<Kit> selectByIds(String kitIds) {
		if (StringUtils.isNotBlank(kitIds)) {
			String[] ids = kitIds.split(",");
			List<Long> kitIdList = new ArrayList<Long>();
			for (String kitId : ids) {
				kitIdList.add(Long.valueOf(kitId));
			}
			if (!CollectionUtils.isEmpty(kitIdList)) {
				LambdaQueryWrapper<Kit> wrapper = new LambdaQueryWrapper<>();
				wrapper.eq(Kit::getIsDelete, IsDeleteEnum.NO.getValue());
				wrapper.in(Kit::getId, kitIdList);
				return kitMapper.selectList(wrapper);
			}
		}
		return null;
	}

	@Override
	public List<Kit> selectByIds(List<Long> kitIds) {
		if(kitIds.size()>0){
			LambdaQueryWrapper<Kit> wrapper = new LambdaQueryWrapper<>();
			wrapper.in(Kit::getId, kitIds);
			return kitMapper.selectList(wrapper);
		}
		return new ArrayList<>();
	}

	@Override
	public int getKitCount(Long labId, Classify classify) {
		LambdaQueryWrapper<Kit> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Kit::getIsDelete, IsDeleteEnum.NO.getValue());
		wrapper.eq(Kit::getLabId, labId);
		wrapper.eq(Kit::getClassify, classify.getValue());
		return kitMapper.selectCount(wrapper);
	}

	@Override
	public int updateAliasBatch(List<Kit> updateKit) {
		return kitMapper.updateAliasBatch(updateKit);
	}

	/**
	 * 新建课题-试剂列表
	 * @param labId
	 * @param pageSize
	 * @param pageNum
	 * @return
	 */
	@Override
	public PageVo<KitInfoListVo> selectMethodReagentList(Long topicTargetId,Long topicExperimentId,Long methodTypeId,Long reagentTypeId,String search,Long labId,Integer pageSize,Integer pageNum) {
		pageNum = pageNum>=1 ? pageNum :1;
		pageSize = pageSize>=1 ? pageSize :1;
		Map<Integer, String> unitMap = dictService.getUnitMap();
		Map<Long, String> reagentTypeMap = dictService.getReagentTypeMap(labId);

		TopicTarget topicTarget=topicTargetService.selectById(topicTargetId);
		Assert.notNull(topicTarget,"课题目标不存在!");
		List<TopicExperiment> topicExperimentList=topicExperimentService.getTopicExperimentList(topicTargetId);
		List<Long> usedMethodTypeIds=topicExperimentList.stream().map(TopicExperiment::getMethodTypeId).distinct().collect(Collectors.toList());
		List<Long> usedMethodIds=topicExperimentList.stream().map(TopicExperiment::getMethodId).distinct().collect(Collectors.toList());

		List<Kit> kitList;
		if (topicExperimentId!=null){
			TopicExperiment topicExperiment = topicExperimentService.selectById(topicExperimentId);
			Assert.notNull(topicExperiment,"课题实验不存在!");
			PageHelper.startPage(pageNum,pageSize);
			kitList = kitMapper.selectMethodReagentList(labId, Classify.REAGENT.getValue(), reagentTypeId , topicExperiment.getMethodTypeId(), search);
		}else {
			PageHelper.startPage(pageNum,pageSize);
			kitList = kitMapper.selectMethodReagentList(labId, Classify.REAGENT.getValue(), reagentTypeId , null, search);
		}

		if (kitList != null && kitList.size() > 0) {
			//用于筛选试剂类型
			List<Long> reagentTypeIds = kitList.stream().map(Kit::getReagentTypeId).distinct().collect(Collectors.toList());
			Map<Long, Long> firstReagentTypeMap = reagentTypeService.selectFirstReagentTypeMap(reagentTypeIds);

			List<Long> kitIds = kitList.stream().map(Kit::getId).collect(Collectors.toList());
			Map<Long, List<FileManage>> fileMap = fileManageService.selectList(OssFileEnum.KitInstructionFile, kitIds).stream().collect(Collectors.groupingBy(FileManage::getReferDataId));
			List<KitInfoListVo> infoListVos=kitList.stream().map(kit -> {
				KitInfoListVo vo=new KitInfoListVo();
				vo.setKitId(kit.getId());
				vo.setKitName(kit.getName());
				vo.setReagentTypeId(kit.getReagentTypeId());
				vo.setReagentTypeName(reagentTypeMap.get(kit.getReagentTypeId()));
				vo.setUnit(kit.getUnit());
				vo.setUnitName(unitMap.get(kit.getUnit()));
				vo.setKitType(kit.getKitType());
				vo.setInstructionFileList(fileMap.get(kit.getId()));
				vo.setRelateMethodId(kit.getRelateMethodId());
				vo.setRelateMethodTypeId(kit.getRelateMethodTypeId());
				vo.setFirstReagentTypeId(firstReagentTypeMap.get(kit.getReagentTypeId()));
				//是否已使用
				if(methodTypeId!=null){
					vo.setHasUsed(usedMethodIds.contains(kit.getRelateMethodId()));
				}else {
					vo.setHasUsed(usedMethodTypeIds.contains(kit.getRelateMethodTypeId()));
				}
				return vo;
			}).collect(Collectors.toList());
			return new PageVo<>(infoListVos);
		}

		return new PageVo<>(pageNum,pageSize,0,new ArrayList<>(0));
	}

	/**
	 * 新建实验-全局试剂方法导入列表
	 * @param labId
	 * @param pageSize
	 * @param pageNum
	 * @return
	 */
	@Override
	public PageVo<KitInfoListVo> selectMethodReagentImportList(Long topicTargetId,Long topicExperimentId, Long methodTypeId, Long reagentTypeId, String search, Long labId, Integer pageSize, Integer pageNum) {
		pageNum = pageNum>=1 ? pageNum :1;
		pageSize = pageSize>=1 ? pageSize :1;
		Map<Integer, String> unitMap = dictService.getUnitMap();
		Map<Long, String> reagentTypeMap = dictService.getReagentTypeMap(labId);

		List<GlobalKit> kitList;
		if (topicExperimentId!=null){
			TopicExperiment topicExperiment = topicExperimentService.selectById(topicExperimentId);
			Assert.notNull(topicExperiment,"课题实验不存在!");
			PageHelper.startPage(pageNum,pageSize);
			kitList = globalKitMapper.selectListWithMethod(labId, Classify.REAGENT.getValue(), reagentTypeId, topicExperiment.getMethodTypeId(),search);
		}else {
			PageHelper.startPage(pageNum,pageSize);
			kitList = globalKitMapper.selectListWithMethod(labId, Classify.REAGENT.getValue(), reagentTypeId, null,search);
		}
		PageHelper.startPage(pageNum,pageSize);
		if (kitList != null && kitList.size() > 0) {
			//用于筛选试剂类型
			List<Long> reagentTypeIds = kitList.stream().map(GlobalKit::getReagentTypeId).distinct().collect(Collectors.toList());
			Map<Long, Long> firstReagentTypeMap = reagentTypeService.selectFirstReagentTypeMap(reagentTypeIds);

			List<Long> kitIds = kitList.stream().map(GlobalKit::getId).collect(Collectors.toList());
			Map<Long, List<FileManage>> fileMap = fileManageService.selectList(OssFileEnum.KitInstructionFile, kitIds).stream().collect(Collectors.groupingBy(FileManage::getReferDataId));
			List<KitInfoListVo> infoListVos=kitList.stream().map(kit -> {
				KitInfoListVo vo=new KitInfoListVo();
				vo.setKitId(kit.getId());
				vo.setKitName(kit.getName());
				vo.setReagentTypeId(kit.getReagentTypeId());
				vo.setReagentTypeName(reagentTypeMap.get(kit.getReagentTypeId()));
				vo.setUnit(kit.getUnit());
				vo.setUnitName(unitMap.get(kit.getUnit()));
				vo.setKitType(kit.getKitType());
				vo.setInstructionFileList(fileMap.get(kit.getId()));
				vo.setRelateMethodId(kit.getRelateMethodId());
				vo.setRelateMethodTypeId(kit.getRelateMethodTypeId());
				vo.setFirstReagentTypeId(firstReagentTypeMap.get(kit.getReagentTypeId()));
				vo.setInstructionFileList(fileManageService.getFileList(kit.getInstruction()));
				//是否已使用
				vo.setHasUsed(false);
				return vo;
			}).collect(Collectors.toList());

			return new PageVo<>(infoListVos);
		}

		return new PageVo<>(pageNum,pageSize,0,new ArrayList<>(0));
	}

}
